#include"../include/img.h"

struct LCD_info *init_lcd(void){
    struct LCD_info *lcd_info = malloc(sizeof(struct LCD_info));
    lcd_info->fd = open("/dev/fb0", O_RDWR);
    if(lcd_info->fd < 0){
        perror("lcd打开失败");
        close(lcd_info->fd);
        return NULL;
    }
    struct fb_var_screeninfo vinfo;
    ioctl(lcd_info->fd, FBIOGET_VSCREENINFO, &vinfo);
    lcd_info->width = vinfo.xres;
    lcd_info->height = vinfo.yres;
    lcd_info->components = vinfo.bits_per_pixel / 8;
    lcd_info->screen_size = lcd_info->width * lcd_info->height * lcd_info->components;
    lcd_info->fb_mem = mmap(NULL, lcd_info->screen_size, PROT_WRITE, MAP_SHARED, lcd_info->fd, 0);
    bzero(lcd_info->fb_mem, lcd_info->screen_size);
    return lcd_info;
}

void release_lcd(struct LCD_info *lcd){
    munmap(lcd->fb_mem, lcd->screen_size);
    close(lcd->fd);
    free(lcd);
    return;
}

void display_img(const char *file_name, uint8_t mode){
    struct LCD_info *lcd = init_lcd();
    FILE *fp = fopen(file_name, "rb");
    if(fp == NULL){
        perror("bmp打开失败");
        close(lcd->fd);
        fclose(fp);
        return;
    }
    struct bitmap_header head;//对bmp结构体名字不熟
    struct bitmap_info info;//对bmp结构体名字不熟
    fread(&head, sizeof(head), 1, fp);
    fread(&info, sizeof(info), 1, fp);//依旧不熟悉参数，fread的第三个参数代表读取数据块的数量
    int quad_size = 0;
    if(info.compression){
        struct rgb_quad quad;//不熟悉该结构体名
        fread(&quad, sizeof(quad), 1, fp);
        quad_size = sizeof(quad);
    }
    //不熟悉接下来读bmp数据的流程
    int rgb_size = head.size - sizeof(head) - sizeof(info) - quad_size;
    char *rgb_data = malloc(rgb_size);
    fread(rgb_data, rgb_size, 1, fp);

    printf("图片规格:%d × %d\n", info.width, info.height);
    printf("色深:%d\n", info.bit_count);

    bool zoom;
    zoom = (info.width > lcd->width || info.height > lcd->height);
    zoom = zoom && (mode & ZOOM);
    printf("zoom:%s\n", zoom ? "True":"False");

    bool center;
    center = (info.width < lcd->width || info.height < lcd->height);
    center = center && (mode & CENTER);
    printf("center:%s\n", center ? "True":"False");

    int pad = (4 - (info.width * info.bit_count/8) %4) %4;
    int lcd_offset = lcd->width * lcd->components;
    int rgb_offset = info.width * info.bit_count/8 + pad;
    int count = 1;
    while(zoom && (info.width/count > lcd->width || info.height/count > lcd->height))
        count++;
    int x = (lcd->width - info.width/count)/2;
    int y = (lcd->height - info.height/count)/2;
    for(int i = y, k = 0; i < lcd->height-y && k < info.height; i++, zoom ? (k+=count) : k++){
        for(int j = x, m = 0; j < lcd->width-x && m < info.width; j++, zoom ? (m+=count) : m++)
            memcpy(lcd->fb_mem + i*lcd_offset + j*lcd->components, 
                rgb_data + (info.height - 1 - k)*rgb_offset + m*info.bit_count/8, 3);//在这一段纠结了一下
    }
    free(rgb_data);
    fclose(fp);
    release_lcd(lcd);
    return;
}
